[IA64] Virtualize ibr/dbr for PV domains.
authorAlex Williamson <alex.williamson@hp.com>
Mon, 2 Jul 2007 14:51:59 +0000 (08:51 -0600)
committerAlex Williamson <alex.williamson@hp.com>
Mon, 2 Jul 2007 14:51:59 +0000 (08:51 -0600)
Signed-off-by: Tristan Gingold <tgingold@free.fr>
xen/arch/ia64/xen/domain.c
xen/arch/ia64/xen/ivt.S
xen/arch/ia64/xen/vcpu.c
xen/include/asm-ia64/domain.h
xen/include/asm-ia64/linux-xen/asm/processor.h

index 83f4472a23dadb362488eb904914ff14ab2e8497..14e529e5bd9370de61b33cc8cd30144d4297c56c 100644 (file)
@@ -237,6 +237,14 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
     ia64_disable_vhpt_walker();
     lazy_fp_switch(prev, current);
 
+    if (prev->arch.dbg_used || next->arch.dbg_used) {
+        /*
+         * Load debug registers either because they are valid or to clear
+         * the previous one.
+         */
+        ia64_load_debug_regs(next->arch.dbr);
+    }
+    
     prev = ia64_switch_to(next);
 
     /* Note: ia64_switch_to does not return here at vcpu initialization.  */
@@ -692,6 +700,14 @@ void arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c)
        c.nat->privregs_pfn = get_gpfn_from_mfn
                (virt_to_maddr(v->arch.privregs) >> PAGE_SHIFT);
 
+       for (i = 0; i < IA64_NUM_DBG_REGS; i++) {
+               vcpu_get_dbr(v, i, &c.nat->regs.dbr[i]);
+               vcpu_get_ibr(v, i, &c.nat->regs.ibr[i]);
+       }
+
+       for (i = 0; i < 7; i++)
+               vcpu_get_rr(v, (unsigned long)i << 61, &c.nat->regs.rr[i]);
+
        /* Fill extra regs.  */
        for (i = 0; i < 8; i++) {
                tr->itrs[i].pte = v->arch.itrs[i].pte.val;
@@ -721,7 +737,7 @@ int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_u c)
        struct domain *d = v->domain;
        int was_initialised = v->is_initialised;
        unsigned int rbs_size;
-       int rc;
+       int rc, i;
 
        /* Finish vcpu initialization.  */
        if (!was_initialised) {
@@ -826,8 +842,12 @@ int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_u c)
                uregs->ar_rsc |= (2 << 2); /* force PL2/3 */
        }
 
+       for (i = 0; i < IA64_NUM_DBG_REGS; i++) {
+               vcpu_set_dbr(v, i, c.nat->regs.dbr[i]);
+               vcpu_set_ibr(v, i, c.nat->regs.ibr[i]);
+       }
+
        if (c.nat->flags & VGCF_EXTRA_REGS) {
-               int i;
                struct vcpu_tr_regs *tr = &c.nat->regs.tr;
 
                for (i = 0; i < 8; i++) {
index 51dbcfbc3f887369e9fa497279aa47f0c2f7dd78..ac4ad3d5b23b19a6573e0d442cfbba7fcf3eec24 100644 (file)
@@ -1183,11 +1183,7 @@ END(speculation_vector)
 // 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56)
 ENTRY(debug_vector)
        DBG_FAULT(29)
-#ifdef XEN
        FAULT_OR_REFLECT(29)
-#else
-       FAULT(29)
-#endif
 END(debug_vector)
 
        .org ia64_ivt+0x5a00
index 120072d4b8c2434a7dbd4d3800d56137e9800dde..d9925667d13e7e9f7ba6e8e84e78856e1c267478 100644 (file)
@@ -1773,33 +1773,61 @@ IA64FAULT vcpu_tak(VCPU * vcpu, u64 vadr, u64 * key)
 
 IA64FAULT vcpu_set_dbr(VCPU * vcpu, u64 reg, u64 val)
 {
-       // TODO: unimplemented DBRs return a reserved register fault
-       // TODO: Should set Logical CPU state, not just physical
-       ia64_set_dbr(reg, val);
+       if (reg >= IA64_NUM_DBG_REGS)
+               return IA64_RSVDREG_FAULT;
+       if ((reg & 1) == 0) {
+               /* Validate address. */
+               if (val >= HYPERVISOR_VIRT_START && val <= HYPERVISOR_VIRT_END)
+                       return IA64_ILLOP_FAULT;
+       } else {
+               /* Mask PL0.  */
+               val &= ~(1UL << 56);
+       }
+       if (val != 0)
+               vcpu->arch.dbg_used |= (1 << reg);
+       else
+               vcpu->arch.dbg_used &= ~(1 << reg);
+       vcpu->arch.dbr[reg] = val;
+       if (vcpu == current)
+               ia64_set_dbr(reg, val);
        return IA64_NO_FAULT;
 }
 
 IA64FAULT vcpu_set_ibr(VCPU * vcpu, u64 reg, u64 val)
 {
-       // TODO: unimplemented IBRs return a reserved register fault
-       // TODO: Should set Logical CPU state, not just physical
-       ia64_set_ibr(reg, val);
+       if (reg >= IA64_NUM_DBG_REGS)
+               return IA64_RSVDREG_FAULT;
+       if ((reg & 1) == 0) {
+               /* Validate address. */
+               if (val >= HYPERVISOR_VIRT_START && val <= HYPERVISOR_VIRT_END)
+                       return IA64_ILLOP_FAULT;
+       } else {
+               /* Mask PL0.  */
+               val &= ~(1UL << 56);
+       }
+       if (val != 0)
+               vcpu->arch.dbg_used |= (1 << (reg + IA64_NUM_DBG_REGS));
+       else
+               vcpu->arch.dbg_used &= ~(1 << (reg + IA64_NUM_DBG_REGS));
+       vcpu->arch.ibr[reg] = val;
+       if (vcpu == current)
+               ia64_set_ibr(reg, val);
        return IA64_NO_FAULT;
 }
 
 IA64FAULT vcpu_get_dbr(VCPU * vcpu, u64 reg, u64 * pval)
 {
-       // TODO: unimplemented DBRs return a reserved register fault
-       u64 val = ia64_get_dbr(reg);
-       *pval = val;
+       if (reg >= IA64_NUM_DBG_REGS)
+               return IA64_RSVDREG_FAULT;
+       *pval = vcpu->arch.dbr[reg];
        return IA64_NO_FAULT;
 }
 
 IA64FAULT vcpu_get_ibr(VCPU * vcpu, u64 reg, u64 * pval)
 {
-       // TODO: unimplemented IBRs return a reserved register fault
-       u64 val = ia64_get_ibr(reg);
-       *pval = val;
+       if (reg >= IA64_NUM_DBG_REGS)
+               return IA64_RSVDREG_FAULT;
+       *pval = vcpu->arch.ibr[reg];
        return IA64_NO_FAULT;
 }
 
@@ -2002,8 +2030,8 @@ unsigned long vcpu_get_rr_ve(VCPU * vcpu, u64 vadr)
 IA64FAULT vcpu_set_rr(VCPU * vcpu, u64 reg, u64 val)
 {
        PSCB(vcpu, rrs)[reg >> 61] = val;
-       // warning: set_one_rr() does it "live"
-       set_one_rr(reg, val);
+       if (vcpu == current)
+               set_one_rr(reg, val);
        return IA64_NO_FAULT;
 }
 
index 6b92bd417b247f0f6d0ef5d15ed938ebe1d28552..0282f34a61efe4cee690a5cb502ce1b0fafd1005 100644 (file)
@@ -180,6 +180,11 @@ struct arch_vcpu {
     int starting_rid;          /* first RID assigned to domain */
     int ending_rid;            /* one beyond highest RID assigned to domain */
 
+    /* Bitset for debug register use.  */
+    unsigned int dbg_used;
+    u64 dbr[IA64_NUM_DBG_REGS];
+    u64 ibr[IA64_NUM_DBG_REGS];
+
     struct thread_struct _thread;      // this must be last
 
     thash_cb_t vtlb;
index fb753e0d16bae5995f07d519b32e3215eb512f17..4a1e07077a7f29143376bc04899259ac688db45c 100644 (file)
@@ -292,11 +292,14 @@ struct thread_struct {
 #else
 # define INIT_THREAD_PM
 #endif
+#ifndef XEN
        __u64 dbr[IA64_NUM_DBG_REGS];
        __u64 ibr[IA64_NUM_DBG_REGS];
+#endif
        struct ia64_fpreg fph[96];      /* saved/loaded on demand */
 };
 
+#ifndef XEN
 #define INIT_THREAD {                                          \
        .flags =        0,                                      \
        .on_ustack =    0,                                      \
@@ -333,6 +336,7 @@ struct thread_struct {
                regs->r1 = 0; regs->r9  = 0; regs->r11 = 0; regs->r13 = 0; regs->r15 = 0;       \
        }                                                                                       \
 } while (0)
+#endif
 
 /* Forward declarations, a strange C thing... */
 struct mm_struct;